package com.newx.file.util;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.BasicSessionCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import com.tencent.cloud.CosStsClient;
import com.tencent.cloud.Response;

import java.io.InputStream;
import java.util.TreeMap;

/**
 * @author yxl
 * @date 2024/7/15 0015 16:29
 */
public class TencentCosUtil {

    /**
     * 上传文件到腾讯云-不使用临时凭证
     * @param inputStream 待上传文件流
     * SECRETID 和 SECRETKEY 请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi 进行查看和管理
     * @param secretId 用户的 SecretId，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
     * @param secretKey 用户的 SecretKey，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
     * @param regionName 阿里云资源访问url(不包含具体资源名称部分)
     * @param oosUrl 指定文件上传到 COS 上的路径，即对象键。例如对象键为 folder/picture.jpg，则表示将文件 picture.jpg 上传到 folder 路径下
     * @param bucketName 指定文件将要存放的存储桶
     * @return
     */
    public static String uploadFile(InputStream inputStream, String oosUrl, String bucketName){
        COSClient cosClient = cosClient();
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, oosUrl, inputStream, null);
        PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
        String region = "ap-beijing"; // 例如：ap-shanghai
        // 构造访问链接
        String url = "https://" + bucketName + ".cos." + region + ".myqcloud.com/" + oosUrl;
        System.out.println("文件访问链接：" + url);
        return url;
    }

    /**
     * 上传文件到腾讯云-使用临时凭证
     * @param inputStream 待上传文件流
     * SECRETID 和 SECRETKEY 请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi 进行查看和管理
     * @param secretId 用户的 SecretId，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
     * @param secretKey 用户的 SecretKey，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
     * @param regionName 阿里云资源访问url(不包含具体资源名称部分)
     * @param oosUrl 指定文件上传到 COS 上的路径，即对象键。例如对象键为 folder/picture.jpg，则表示将文件 picture.jpg 上传到 folder 路径下
     * @param bucketName 指定文件将要存放的存储桶
     * @return
     */
    public static String uploadFileByToken(InputStream inputStream, String oosUrl, String bucketName){
        //COSClient cosClient = cosClient();
        COSClient cosClient = cosClientByToken();
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, oosUrl, inputStream, null);
        PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
        String region = "ap-beijing"; // 例如：ap-shanghai
        // 构造访问链接
        String url = "https://" + bucketName + ".cos." + region + ".myqcloud.com/" + oosUrl;
        System.out.println("文件访问链接：" + url);
        return url;
    }

    /**
     * 获取腾讯云COS客户端(不使用临时密钥)
     * @return
     */
    public static COSClient cosClient(){
        // 1 初始化用户身份信息（secretId, secretKey）。
        COSCredentials cred = new BasicCOSCredentials("AKIDSny1vhFexYGAFOWZbYNA3wdAWlpiR6hA", "TjqsodMv7QoItYQMOZtOl4HNL8pKiv1v");
        // 2 设置 bucket 的地域, COS 地域的简称请参见 https://cloud.tencent.com/document/product/436/6224
        // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
        Region region = new Region("ap-beijing");
        ClientConfig clientConfig = new ClientConfig(region);
        // 这里建议设置使用 https 协议
        // 从 5.6.54 版本开始，默认使用了 https
        clientConfig.setHttpProtocol(HttpProtocol.https);
        // 3 生成 cos 客户端。
        COSClient cosClient = new COSClient(cred, clientConfig);
        return cosClient;
    }

    /**
     * 获取腾讯云COS客户端（使用临时密钥）
     * @return
     */
    public static COSClient cosClientByToken(){
        Response response = getCredentialToken();
        // 1 传入获取到的临时密钥 (tmpSecretId, tmpSecretKey, sessionToken)
        String tmpSecretId = response.credentials.tmpSecretId;
        String tmpSecretKey = response.credentials.tmpSecretKey;
        String sessionToken = response.credentials.sessionToken;
        BasicSessionCredentials cred = new BasicSessionCredentials(tmpSecretId, tmpSecretKey, sessionToken);
        // 2 设置 bucket 的地域
        // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分
        Region region = new Region("ap-beijing"); //COS_REGION 参数：配置成存储桶 bucket 的实际地域，例如 ap-beijing，更多 COS 地域的简称请参见 https://cloud.tencent.com/document/product/436/6224
        ClientConfig clientConfig = new ClientConfig(region);
        // 3 生成 cos 客户端
        return new COSClient(cred, clientConfig);
    }

    /**
     * 基本的临时密钥申请示例，适合对一个桶内的一批对象路径，统一授予一批操作权限
     */
    public static Response  getCredentialToken() {
        TreeMap<String, Object> config = new TreeMap<String, Object>();
        try {
            // 云 api 密钥 SecretId
            config.put("secretId", "AKIDSny1vhFexYGAFOWZbYNA3wdAWlpiR6hA");
            // 云 api 密钥 SecretKey
            config.put("secretKey", "TjqsodMv7QoItYQMOZtOl4HNL8pKiv1v");

            // 设置域名,可通过此方式设置内网域名
            //config.put("host", "sts.internal.tencentcloudapi.com");

            // 临时密钥有效时长，单位是秒
            config.put("durationSeconds", 1800);

            // 换成你的 bucket
            config.put("bucket", "xincaiyuan-1320074649");
            // 换成 bucket 所在地区
            config.put("region", "ap-beijing");

            // 可以通过 allowPrefixes 指定前缀数组, 例子： a.jpg 或者 a/* 或者 * (使用通配符*存在重大安全风险, 请谨慎评估使用)
            config.put("allowPrefixes", new String[] {
                    "*",
            });
            // 密钥的权限列表。简单上传和分片需要以下的权限，其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
            String[] allowActions = new String[] {
                    // 简单上传
                    "name/cos:PutObject",
                    "name/cos:PostObject",
                    // 分片上传
                    "name/cos:InitiateMultipartUpload",
                    "name/cos:ListMultipartUploads",
                    "name/cos:ListParts",
                    "name/cos:UploadPart",
                    "name/cos:CompleteMultipartUpload"
            };
            config.put("allowActions", allowActions);
            Response response = CosStsClient.getCredential(config);
            //System.out.println(response.credentials.tmpSecretId);
            //System.out.println(response.credentials.tmpSecretKey);
            //System.out.println(response.credentials.sessionToken);
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            throw new IllegalArgumentException("no valid secret !");
        }
    }
}
